package com.aizuda.boot.modules.business.permission.provider.impl;

import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.common.constant.enums.ResponseCodeEnum;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.department.domain.response.DepartmentShowVO;
import com.aizuda.boot.modules.business.employee.service.EmployeeService;
import com.aizuda.boot.modules.business.permission.domain.entity.RoleDataIsolationConditionEntity;
import com.aizuda.boot.modules.business.permission.domain.entity.RoleDataIsolationEntity;
import com.aizuda.boot.modules.business.permission.domain.request.AddPermissionVO;
import com.aizuda.boot.modules.business.permission.domain.request.GetPermissionPageVO;
import com.aizuda.boot.modules.business.permission.domain.request.UpdatePermissionVO;
import com.aizuda.boot.modules.business.permission.domain.response.EmployeeShowVO;
import com.aizuda.boot.modules.business.permission.domain.response.PagePermissionVO;
import com.aizuda.boot.modules.business.permission.domain.response.PermissionShowVO;
import com.aizuda.boot.modules.business.permission.domain.response.RoleDataIsolationConditionShowVO;
import com.aizuda.boot.modules.business.permission.provider.PermissionProvider;
import com.aizuda.boot.modules.business.permission.service.RoleDataIsolationConditionService;
import com.aizuda.boot.modules.business.permission.service.RoleDataIsolationService;
import com.aizuda.boot.modules.business.permission.service.RolePermissionService;
import com.aizuda.boot.modules.common.constant.enums.ContractScopeTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.DataType;
import com.aizuda.boot.modules.common.constant.enums.PermissionStatusType;
import com.aizuda.boot.modules.common.constant.enums.ValidityType;
import com.aizuda.boot.modules.system.entity.SysRole;
import com.aizuda.boot.modules.system.service.ISysDepartmentService;
import com.aizuda.boot.modules.system.service.ISysRoleService;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : bushiduanyao,hainengshishui
 */
@Service
@Slf4j
public class PermissionProviderImpl implements PermissionProvider {

    @Autowired
    private RoleDataIsolationService roleDataIsolationService;
    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private RoleDataIsolationConditionService roleDataIsolationConditionService;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISysRoleService sysRoleService;

    @Resource
    private ISysDepartmentService sysDepartmentService;

    /**
     * 根据权限id获取权限信息
     *
     * @param permissionId 权限id
     * @return
     */
    @Override
    public SingleResponse<PermissionShowVO> getPermission(Long permissionId) {
        if (null == permissionId) {
            return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        // 获取权限信息
        RoleDataIsolationEntity roleDataIsolation = roleDataIsolationService.getById(permissionId);
        PermissionShowVO permissionShowVO = new PermissionShowVO();
        // 判断关联值
        if (Objects.isNull(roleDataIsolation)) {
            return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
        }
        // 获取用户关联
        if (!StringUtils.isEmpty(roleDataIsolation.getUserId())) {
            String[] userIdArray = roleDataIsolation.getUserId().split(",");
            permissionShowVO.setGrantUsers(Arrays.stream(userIdArray).map(Long::valueOf).collect(Collectors.toList()));
            permissionShowVO.setGrantUserType("user");
        }
        // 获取去部门关联
        if (!StringUtils.isEmpty(roleDataIsolation.getDepartmentId())) {
            String[] departIdArray = roleDataIsolation.getDepartmentId().split(",");
            permissionShowVO.setGrantDepartments(Arrays.stream(departIdArray).map(Long::valueOf).collect(Collectors.toList()));
            permissionShowVO.setGrantUserType("department");
        }
        // 获取角色关联
        if (null != roleDataIsolation.getRoleId() && roleDataIsolation.getRoleId() != 0) {
            Long roleId = roleDataIsolation.getRoleId();
            SysRole role = sysRoleService.getById(roleId);
            if (!Objects.isNull(role)) {
                permissionShowVO.setGrantRole(role.getId().toString());
                permissionShowVO.setGrantUserType("role");
            }
        }
        // 使用自定义权限条件
        if (roleDataIsolation.getUseCustomCondition().equals(true)) {
            List<RoleDataIsolationConditionEntity> conditionEntities = roleDataIsolationConditionService.list(
                    new LambdaQueryWrapper<RoleDataIsolationConditionEntity>()
                            .eq(RoleDataIsolationConditionEntity::getPermissionId, permissionId)
            );

            if (!CollectionUtils.isEmpty(conditionEntities)) {
                // 构建条件树
                Map<Long, RoleDataIsolationConditionShowVO> conditionMap = new HashMap<>();
                List<RoleDataIsolationConditionShowVO> rootConditions = new ArrayList<>();

                // 第一步：将所有条件转换为ShowVO并放入Map
                for (RoleDataIsolationConditionEntity entity : conditionEntities) {
                    RoleDataIsolationConditionShowVO showVO = new RoleDataIsolationConditionShowVO();
                    BeanUtils.copyProperties(entity, showVO);
                    showVO.setId(entity.getConditionId());
                    showVO.setChildConditionList(new ArrayList<>());
                    conditionMap.put(entity.getConditionId(), showVO);
                }

                // 第二步：构建树形结构
                for (RoleDataIsolationConditionEntity entity : conditionEntities) {
                    RoleDataIsolationConditionShowVO showVO = conditionMap.get(entity.getConditionId());
                    if (entity.getParentConditionId() == null) {
                        // 根条件
                        rootConditions.add(showVO);
                    } else {
                        // 子条件
                        RoleDataIsolationConditionShowVO parentVO = conditionMap.get(entity.getParentConditionId());
                        if (parentVO != null) {
                            parentVO.getChildConditionList().add(showVO);
                        }
                    }
                }
                permissionShowVO.setCustomCondition(rootConditions);
            }
        }
        //赋值
        permissionShowVO.setPermissionId(roleDataIsolation.getPermissionId());
        permissionShowVO.setName(roleDataIsolation.getPermissionName());
        permissionShowVO.setValidType(roleDataIsolation.getValidityType());
        if (ValidityType.FIXED_DATE.equals(roleDataIsolation.getValidityType())) {
            permissionShowVO.setValidRange(new ArrayList<>());
            permissionShowVO.getValidRange().add(roleDataIsolation.getValidityStartDate());
            permissionShowVO.getValidRange().add(roleDataIsolation.getValidityEndDate());
        }
        permissionShowVO.setDataType(roleDataIsolation.getDataType());
        if (DataType.CONTRACT.equals(roleDataIsolation.getDataType())) {
            permissionShowVO.setContractScope(roleDataIsolation.getContractScope());
        } else {
            permissionShowVO.setNegotiationScope(roleDataIsolation.getContractScope());
        }
        permissionShowVO.setCreatedAt(roleDataIsolation.getCreatedAt());
        return SingleResponse.of(permissionShowVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> addPermission(AddPermissionVO addPermissionVO) {
        UserInfo currentUser = AuthUtil.getCurrentUser();
        if (Objects.isNull(currentUser.getEmployeeId())){
           return SingleResponse.failure(ResponseCodeEnum.NOT_LOGGED.getCode(), ResponseCodeEnum.NOT_LOGGED.getMsg());
        }
        // 参数校验
        if (null == addPermissionVO) {
           return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        long count = roleDataIsolationService.count(new LambdaQueryWrapper<RoleDataIsolationEntity>()
                .eq(RoleDataIsolationEntity::getPermissionName, addPermissionVO.getName()));
        if (count > 0) {
            return SingleResponse.failure(ResponseCodeEnum.DATA_ALREADY_EXISTS.getCode(), "权限已存在");
        }
        // 创建实体
        RoleDataIsolationEntity roleDataIsolation = new RoleDataIsolationEntity();
        // 赋值
        roleDataIsolation.setPermissionName(addPermissionVO.getName());
        // 用户类型
        if (addPermissionVO.getGrantUserType().equals("user")) {
            roleDataIsolation.setUserId(String.join(",", addPermissionVO.getGrantUsers()));
        }
        // 部门类型
        if (addPermissionVO.getGrantUserType().equals("department")) {
            roleDataIsolation.setDepartmentId(String.join(",", addPermissionVO.getGrantDepartments()));
        }
        // 角色类型
        if (addPermissionVO.getGrantUserType().equals("role")) {
            roleDataIsolation.setRoleId(Long.parseLong(addPermissionVO.getRoleId()));
        }
        // 有效期类型
        if (addPermissionVO.getValidType().equals(ValidityType.FIXED_DATE)) {
            //  判断有效期
            if (addPermissionVO.getValidRange().get(1).before(new Date())) {
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), "有效期不能小于当前时间");
            }
            roleDataIsolation.setValidityType(ValidityType.FIXED_DATE);
            roleDataIsolation.setValidityStartDate(addPermissionVO.getValidRange().get(0));
            roleDataIsolation.setValidityEndDate(addPermissionVO.getValidRange().get(1));
            if (addPermissionVO.getValidRange().get(0).after(new Date())) {
                roleDataIsolation.setPermissionStatus(PermissionStatusType.UN_ENABLE);
            } else {
                roleDataIsolation.setPermissionStatus(PermissionStatusType.ENABLE);
            }
        } else {
            // 永久
            roleDataIsolation.setValidityType(ValidityType.PERMANENT);
            roleDataIsolation.setPermissionStatus(PermissionStatusType.ENABLE);
        }
        // 数据类型
        roleDataIsolation.setDataType(addPermissionVO.getDataType());
        if (DataType.CONTRACT.equals(addPermissionVO.getDataType())) {
            roleDataIsolation.setContractScope(addPermissionVO.getContractScope());
        } else {
            roleDataIsolation.setContractScope(ContractScopeTypeEnums.ALL);
        }
        // 是否使用自定义条件
        roleDataIsolation.setUseCustomCondition(ContractScopeTypeEnums.CUSTOM.equals(addPermissionVO.getContractScope()));
        roleDataIsolationService.save(roleDataIsolation);
        if (roleDataIsolation.getUseCustomCondition()) {
            roleDataIsolationConditionService.saveCustom(roleDataIsolation.getId(), addPermissionVO.getCustomCondition());
        }
        return SingleResponse.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> enable(Long permissionId) {
        if (Objects.isNull(permissionId)) {
           return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        RoleDataIsolationEntity roleDataIsolation = roleDataIsolationService.getById(permissionId);
        if (null == roleDataIsolation) {
           return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
        }
        roleDataIsolation.setPermissionStatus(roleDataIsolation.getPermissionStatus().equals(PermissionStatusType.ENABLE) ? PermissionStatusType.DISABLE : PermissionStatusType.ENABLE);
        roleDataIsolation.setUpdatedAt(new Date());
        roleDataIsolationService.updateById(roleDataIsolation);
        return SingleResponse.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> updatePermission(UpdatePermissionVO addPermissionVO) {
        UserInfo currentUser = AuthUtil.getCurrentUser();
        if (Objects.isNull(currentUser.getEmployeeId())){
           return SingleResponse.failure(ResponseCodeEnum.NOT_LOGGED.getCode(), ResponseCodeEnum.NOT_LOGGED.getMsg());
        }
        // 参数校验
        if (Objects.isNull(addPermissionVO) || null == addPermissionVO.getPermissionId()) {
           return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        RoleDataIsolationEntity roleDataIsolation = roleDataIsolationService.getById(addPermissionVO.getPermissionId());
        if (null == roleDataIsolation) {
           return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
        }
        long count = roleDataIsolationService.count(new LambdaQueryWrapper<RoleDataIsolationEntity>()
                .ne(RoleDataIsolationEntity::getPermissionId, addPermissionVO.getPermissionId())
                .eq(RoleDataIsolationEntity::getPermissionName, addPermissionVO.getName()));
        if (count > 0) {
           return SingleResponse.failure(ResponseCodeEnum.DATA_ALREADY_EXISTS.getCode(), "权限已存在");
        }
        // 赋值
        roleDataIsolation.setPermissionName(addPermissionVO.getName());
        // 用户类型
        if (addPermissionVO.getGrantUserType().equals("user")) {
            roleDataIsolation.setUserId(String.join(",", addPermissionVO.getGrantUsers()));
        } else {
            roleDataIsolation.setUserId(null);
        }
        // 部门类型
        if (addPermissionVO.getGrantUserType().equals("department")) {
            roleDataIsolation.setDepartmentId(String.join(",", addPermissionVO.getGrantDepartments()));
        } else {
            roleDataIsolation.setDepartmentId(null);
        }
        // 角色类型
        if (addPermissionVO.getGrantUserType().equals("role")) {
            roleDataIsolation.setRoleId(Long.parseLong(addPermissionVO.getRoleId()));
        } else {
            roleDataIsolation.setRoleId(null);
        }
        // 有效期类型
        if (addPermissionVO.getValidType().equals(ValidityType.FIXED_DATE)) {
            //  判断有效期
            if (addPermissionVO.getValidRange().get(1).before(new Date())) {
               return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), "有效期结束日期不能早于当前日期");
            }
            roleDataIsolation.setValidityType(ValidityType.FIXED_DATE);
            roleDataIsolation.setValidityStartDate(addPermissionVO.getValidRange().get(0));
            roleDataIsolation.setValidityEndDate(addPermissionVO.getValidRange().get(1));
            if (addPermissionVO.getValidRange().get(0).after(new Date())) {
                roleDataIsolation.setPermissionStatus(PermissionStatusType.UN_ENABLE);
            } else {
                roleDataIsolation.setPermissionStatus(PermissionStatusType.ENABLE);
            }
        } else {
            // 永久
            roleDataIsolation.setValidityType(ValidityType.PERMANENT);
            roleDataIsolation.setPermissionStatus(PermissionStatusType.ENABLE);
            roleDataIsolation.setValidityStartDate(null);
            roleDataIsolation.setValidityEndDate(null);
        }
        // 数据类型
        roleDataIsolation.setDataType(addPermissionVO.getDataType());
        if (DataType.CONTRACT.equals(addPermissionVO.getDataType())) {
            roleDataIsolation.setContractScope(addPermissionVO.getContractScope());
        } else {
            roleDataIsolation.setContractScope(ContractScopeTypeEnums.ALL);
        }
        // 是否使用自定义条件
        roleDataIsolation.setUseCustomCondition(ContractScopeTypeEnums.CUSTOM.equals(addPermissionVO.getContractScope()));

        roleDataIsolationService.updateById(roleDataIsolation);
//        roleDataIsolationConditionService.remove(new LambdaQueryWrapper<RoleDataIsolationConditionEntity>()
//                .eq(RoleDataIsolationConditionEntity::getPermissionId, roleDataIsolation.getPermissionId()));
        // 是否选择自定义合同
//        if (roleDataIsolation.getUseCustomCondition()) {
//            roleDataIsolationConditionService.saveCustom(roleDataIsolation.getPermissionId(), addPermissionVO.getCustomCondition());
//        }
        return SingleResponse.success();
    }

    @Override
    public SingleResponse<IPage<PagePermissionVO>> pagePermission(IPage<PagePermissionVO> page, GetPermissionPageVO vo) {
        UserInfo currentUser = AuthUtil.getCurrentUser();
        if (Objects.isNull(currentUser.getEmployeeId())){
           return SingleResponse.failure(ResponseCodeEnum.NOT_LOGGED.getCode(), ResponseCodeEnum.NOT_LOGGED.getMsg());
        }
        if (Objects.isNull(page) || page.getSize() < 1 || page.getCurrent() < 1) {
           return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }
        List<String> list = null;
        if (StringUtils.hasText(vo.getUserId())) {
            String[] userArray = vo.getUserId().split(",");
            list = Arrays.asList(userArray);
        }
        page = rolePermissionService.pagePermission(page, vo, list);
        List<PagePermissionVO> records = page.getRecords().stream().map(permission -> {
            if (null == permission) {
                return new PagePermissionVO();
            }
            if (StringUtils.hasText(permission.getUserId())) {
                String[] userIdArray = permission.getUserId().split(",");
                List<EmployeeShowVO> employeeShowVOList = sysUserService.listByIds(Arrays.asList(userIdArray))
                        .stream().map(employee -> {
                            EmployeeShowVO employeeShowVO = new EmployeeShowVO();
                            employeeShowVO.setId(employee.getId());
                            employeeShowVO.setName(employee.getNickName());
                            employeeShowVO.setAvatar(employee.getAvatar());
                            return employeeShowVO;
                        }).collect(Collectors.toList());
                permission.setUserVOS(employeeShowVOList);
            }
            if (StringUtils.hasText(permission.getDepartmentId())) {
                String[] departmentIdArray = permission.getDepartmentId().split(",");
                List<DepartmentShowVO> departmentShowVOList = sysDepartmentService.listByIds(Arrays.asList(departmentIdArray))
                        .stream().map(department -> {
                            DepartmentShowVO departmentShowVO = new DepartmentShowVO();
                            departmentShowVO.setId(department.getId());
                            departmentShowVO.setNodeId(department.getId());
                            departmentShowVO.setNodeParentId(department.getPid());
                            departmentShowVO.setName(department.getName());
                            departmentShowVO.setCode(department.getCode());
                            departmentShowVO.setRemark(department.getRemark());
                            departmentShowVO.setSort(department.getSort());
                            departmentShowVO.setEnable(department.getStatus());
                            return departmentShowVO;
                        }).collect(Collectors.toList());
                permission.setDepartmentVOS(departmentShowVOList);
            }
            if (null != permission.getRoleId() && permission.getRoleId() != 0) {
                SysRole roleEntity = sysRoleService.getById(permission.getRoleId());
                if (null != roleEntity) {
                    permission.setRoleName(roleEntity.getName());
                }
            }
            return permission;
        }).collect(Collectors.toList());
        page.setRecords(records);
        return SingleResponse.of(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> del(Long permissionId) {
        // 1. 参数校验
        if (Objects.isNull(permissionId)) {
           return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
        }

        // 2. 检查权限是否存在
        RoleDataIsolationEntity roleDataIsolation = roleDataIsolationService.getById(permissionId);
        if (Objects.isNull(roleDataIsolation)) {
           return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
        }

        // 3. 检查权限状态
        if (PermissionStatusType.ENABLE.equals(roleDataIsolation.getPermissionStatus())) {
           return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), "该权限已启用,无法删除");
        }
        // 删除自定义条件
//        roleDataIsolationConditionService.remove(
//                new LambdaQueryWrapper<RoleDataIsolationConditionEntity>()
//                        .eq(RoleDataIsolationConditionEntity::getPermissionId, permissionId)
//        );

        // 删除权限
        boolean result = roleDataIsolationService.removeById(permissionId);
        if (!result) {
           return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), "删除权限失败");
        }
        return SingleResponse.success();
    }
} 